//
//  PeerTalkHelper+PTChannelDelegate.swift
//  PeerTalkPlaygroundWithSPM
//
//  Created by treastrain on 2021/05/15.
//

import Foundation
import PeerTalk
import AppKit

var pCount: Int64 = 0
@available(macOS 13.0, *)
extension PeerTalkHelper: PTChannelDelegate {
#if os(iOS) || os(tvOS)
    func channel(_ channel: PTChannel, didAcceptConnection otherChannel: PTChannel, from address: PTAddress) {
        if self.peerChannel != nil {
            self.peerChannel?.cancel()
        }
        
        self.peerChannel = otherChannel
        self.peerChannel?.userInfo = address
        self.addMessage("✅ Connected to \(address)")
    }
#endif
    
    func channel(_ channel: PTChannel, shouldAcceptFrame type: UInt32, tag: UInt32, payloadSize: UInt32) -> Bool {
#if os(iOS) || os(tvOS)
        guard channel == self.peerChannel else {
            return false
        }
#endif
        
        guard type == Settings.frameType else {
            ELog.d( #function, "Unexpected frame of type \(type)", #line)
            channel.close()
            return false
        }
        
        return true
    }
    
    func channel(_ channel: PTChannel, didRecieveFrame type: UInt32, tag: UInt32, payload: Data?) {
        guard type == Settings.frameType else {
            ELog.d(#function, "Unexpected frame of type \(type)", #line)
            channel.close()
            return
        }
        
        DispatchSerialQueue.global(qos: .userInteractive).async {
            guard let payload = payload else {
                return
            }
            //  print(  channel.userInfo)
            payload.withUnsafeBytes { [self] buffer in
                let textBytes = buffer[(buffer.startIndex + MemoryLayout<UInt32>.size)...]
                if var message = String(bytes: textBytes, encoding: .utf8) {
                    
                    var json = toJsonDictionary(jsonString: message)
                    ELog.d(#function, json["result"] as! String, #line)
                    
                    let action = json["action"] as! Int
                    //    print("Action: ", action)
                    if (action == 8) {
                        
                        pCount = pCount + 1
                        
                        ELog.d(#function, "\(pCount), Message received ", #line)
                        
                        let base64 = json["data"] as! String
                        if (base64  != "") {
                            var image = fromBase64(base64String: base64 )
                            if (image == nil) {
                                image = NSImage(size: NSSize(width: 1, height: 1))
                                
                                PavaoManager.instance.saveLog(logLevel: .warning, logContent: "Delegate: Image == nil, saving dummy image")
                            }
                            
                            if (self.isSendingToElefante) {
                                DispatchQueue.global(qos: .background).async {
                                    
                                    self.postImageToURL(image: image!, url: URL(string: "http://127.0.0.1:11111")!) { (data, response, error) in
                                        ELog.d(#function, response?.description ?? "", #line)
                                    }
                                }
                            }
                            json.removeValue(forKey: "data")
                            message = jsonDictToString(jsonDict: json)
                            
                            let devices_ = devices.filter { device in
                                device.channel == channel
                            }
                            devices_[0].results = json["result"] as! String
                            let imageDir = devices_[0].imageDir
                            ELog.d(#function, imageDir.path(), #line)
                            if (imageDir.path() != "./") {
                                // Write the image data to the file
                                let date = Date.now
                                let millisecond = date.timeIntervalSince1970.truncatingRemainder(dividingBy: 1)
                                let milStr =  String(millisecond)
                                var milOffset = 6
                                if ((milStr.count - 1) < milOffset) {
                                    milOffset = milStr.count - 1
                                }
                                let filePath =  date.ISO8601Format() + milStr[milStr.index(milStr.startIndex, offsetBy: 2) ...  milStr.index(milStr.startIndex, offsetBy: milOffset)] + ".png"
                                let fileUrl = imageDir.appending(path:filePath)
                                
                                ELog.d(#function,fileUrl.absoluteString, #line)
                                
                                do {
                                    try image?.tiffRepresentation!.write(to: fileUrl)
                                    PavaoManager.instance.saveLog(logLevel: .debug, logContent: "Delegate: Image saving success at \(fileUrl)")
                                    // The image has been successfully saved to the fileURL
                                } catch {
                                    // Handle the error
                                    ELog.e(#function, "Error saving image: \(error)", #line)
                                    PavaoManager.instance.saveLog(logLevel: .warning, logContent: "Delegate: Image saving failure at \(fileUrl), \(error)")
                                }
                            } 
                        }
                        //   json["file_url"] = fileURL
                    }
                    
                    
#if os(iOS) || os(tvOS)
                    addMessage("💻 \(message)")
#elseif os(macOS)
                    //    addMessage("📱 \(message)")
#else
                    addMessage("❓ \(message)")
#endif
                } else {
                    PavaoManager.instance.saveLog(logLevel: .error, logContent: "USBMUXD JSON INVALID")
                }
            }
        }
        
    }
    
    
    func postImageToURL(image: NSImage, url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
        guard let imageData = image.tiffRepresentation else {
            ELog.e(String(describing: type(of: self)),#function, "Failed to convert image to data.", #line)
            return
        }
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("image/jpeg", forHTTPHeaderField: "Content-Type")
        request.httpBody = imageData
        
        let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
            completion(data, response, error)
        }
        task.resume()
    }
    
    
    
    func fromBase64(base64String: String) -> NSImage? {
        guard let imageData = Data(base64Encoded: base64String) else { return nil }
        return NSImage(data: imageData)
    }
    
    
    func channelDidEnd(_ channel: PTChannel, error: Error?) {
#if os(iOS) || os(tvOS)
        if let error = error {
            self.addMessage("❌ \(channel) ended with error: \(error)")
        } else {
            self.addMessage("📴 Disconnected from \(channel.userInfo)")
        }
#elseif os(macOS)
        if let connectedDeviceID = self.connectedDeviceID,
           let deviceID = channel.userInfo as? NSNumber,
           connectedDeviceID.isEqual(to: deviceID) {
            self.didDisconnect(from: self.connectedDeviceID!)
        }
        
        if self.peerChannel == channel {
            ELog.d(String(describing: type(of: self)),#function, "📴 Disconnected from \(channel.userInfo)", #line)
            PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.warning, logContent: "📴 Disconnected from \(channel.userInfo)")
            self.peerChannel = nil
        }
#endif
    }
}
